// ===============================================================
// ee_hqxaa  Hilda,
// this is a program to test read SD card and write VS decoder
// version 1.0  @ 25 July
//================================================================


#define F_CPU 7372800UL

#include <avr/io.h>
#include <util/delay.h>
#include "FAT.h"
#include "SD.h"
#include "VS.h"



#define SPI_SCK		1
#define SPI_MOSI	2
#define SPI_MISO	3

#define SPI_PORT		PORTB
#define SPI_DDR			DDRB


#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long


#define PATH (unsigned char *) ("\\")


extern unsigned char  FAT32_Enable;
//extern uint16 data[];					// to sample music by timer interrupt
extern unsigned char *cnt;
extern unsigned int SectorsPerClust;
extern unsigned long FirstFATSector;
extern unsigned long FirstDirSector;
extern unsigned long FirstDataSector;
extern unsigned char (*FAT_ReadSector)(DWORD sector, BYTE * buffer);

unsigned char num_songs;						// total number of songs
unsigned char file_type = 1;					// we support only mp3 file type now, maybe we can add wma, and midi later
unsigned char track_info[128];					// song's information stored in file's header


struct FileInfoStruct FileInfo;
struct direntry MusicInfo;



#define DEBUGLED1_CON() DDRA|=_BV(PA0)
#define DEBUGLED1_ON()  PORTA|=_BV(PA0)
#define DEBUGLED1_OFF() PORTA&=~_BV(PA0)

#define DEBUGLED2_CON() DDRA|=_BV(PA1)
#define DEBUGLED2_ON()  PORTA|=_BV(PA1)
#define DEBUGLED2_OFF() PORTA&=~_BV(PA1)

#define DEBUGLED3_CON() DDRA|=_BV(PA2)
#define DEBUGLED3_ON()  PORTA|=_BV(PA2)
#define DEBUGLED3_OFF() PORTA&=~_BV(PA2)

#define DEBUGLED4_CON() DDRA|=_BV(PA3)
#define DEBUGLED4_ON()  PORTA|=_BV(PA3)
#define DEBUGLED4_OFF() PORTA&=~_BV(PA3)

#define DEBUGLED5_CON() DDRA|=_BV(PA4)
#define DEBUGLED5_ON()  PORTA|=_BV(PA4)
#define DEBUGLED5_OFF() PORTA&=~_BV(PA4)

#define DEBUGLED6_CON() DDRA|=_BV(PA5)
#define DEBUGLED6_ON()  PORTA|=_BV(PA5)
#define DEBUGLED6_OFF() PORTA&=~_BV(PA5)

#define DEBUGLED7_CON() DDRA|=_BV(PA6)
#define DEBUGLED7_ON()  PORTA|=_BV(PA6)
#define DEBUGLED7_OFF() PORTA&=~_BV(PA6)

#define DEBUGLED8_CON() DDRA|=_BV(PA7)
#define DEBUGLED8_ON()  PORTA|=_BV(PA7)
#define DEBUGLED8_OFF() PORTA&=~_BV(PA7)


void delay500ms(){
	unsigned char cnt;
	for(cnt = 0; cnt< 30; cnt++){
		_delay_ms(20);
	}
}



//=================================================
//===this is for debug , UART output to monintor===
//=================================================

void U_32(unsigned long read){
	uint32 read32;
	//uint16 read16;
	//unsigned int Ucnt;
	unsigned char ascii;
	unsigned char asciih;
	unsigned char asciil;

	read32 = read;
	ascii = read32>>24;
			asciih = ascii>>4;
			asciil = ascii<<4;
			asciil>>=4;

			while(!(UCSR0A&(1<<UDRE0)));
			if (asciih<0x0a)
				 UDR0 = (asciih + 0x30);			//123456789
			 else UDR0 = (asciih + 0x37);		//abcde

			while(!(UCSR0A&(1<<UDRE0)));
			 if (asciil<0x0a)
				 UDR0 = (asciil + 0x30);			//123456789
			 else UDR0 = (asciil + 0x37);		//abcde


				ascii = read32>>16;
						asciih = ascii>>4;
						asciil = ascii<<4;
						asciil>>=4;

						while(!(UCSR0A&(1<<UDRE0)));
						if (asciih<0x0a)
							 UDR0 = (asciih + 0x30);			//123456789
						 else UDR0 = (asciih + 0x37);		//abcde

						while(!(UCSR0A&(1<<UDRE0)));
						 if (asciil<0x0a)
							 UDR0 = (asciil + 0x30);			//123456789
						 else UDR0 = (asciil + 0x37);		//abcde


							ascii = read32>>8;
									asciih = ascii>>4;
									asciil = ascii<<4;
									asciil>>=4;

									while(!(UCSR0A&(1<<UDRE0)));
									if (asciih<0x0a)
										 UDR0 = (asciih + 0x30);			//123456789
									 else UDR0 = (asciih + 0x37);		//abcde

									while(!(UCSR0A&(1<<UDRE0)));
									 if (asciil<0x0a)
										 UDR0 = (asciil + 0x30);			//123456789
									 else UDR0 = (asciil + 0x37);		//abcde


											ascii = read32;
													asciih = ascii>>4;
													asciil = ascii<<4;
													asciil>>=4;

													while(!(UCSR0A&(1<<UDRE0)));
													if (asciih<0x0a)
														 UDR0 = (asciih + 0x30);			//123456789
													 else UDR0 = (asciih + 0x37);		//abcde

													while(!(UCSR0A&(1<<UDRE0)));
													 if (asciil<0x0a)
														 UDR0 = (asciil + 0x30);			//123456789
													 else UDR0 = (asciil + 0x37);		//abcde



}


void U_512(unsigned char * buffer){
	unsigned int Ucnt;
	unsigned char ascii;
	unsigned char asciih;
	unsigned char asciil;
	for(Ucnt = 0; Ucnt<512; Ucnt++){
		ascii = buffer[Ucnt];
			asciih = ascii>>4;
			asciil = ascii<<4;
			asciil>>=4;

		while(!(UCSR0A&(1<<UDRE0)));
		if (asciih<0x0a)
			 UDR0 = (asciih + 0x30);			//123456789
		 else UDR0 = (asciih + 0x37);		//abcde

		while(!(UCSR0A&(1<<UDRE0)));
		 if (asciil<0x0a)
			 UDR0 = (asciil + 0x30);			//123456789
		 else UDR0 = (asciil + 0x37);		//abcde
	}
}


//=================================================
//=================================================










//=================================================================
// first, we try to play the first song
//=================================================================


int main(void){

	DDRA = 0xff;

	delay500ms();

	DEBUGLED1_CON();					// initialize debug led
	DEBUGLED1_OFF();
	DEBUGLED2_CON();
	DEBUGLED2_OFF();
	DEBUGLED3_CON();					// initialize debug led
	DEBUGLED3_OFF();
	DEBUGLED4_CON();
	DEBUGLED4_OFF();
	DEBUGLED5_CON();					// initialize debug led
	DEBUGLED5_OFF();
	DEBUGLED6_CON();
	DEBUGLED6_OFF();
	DEBUGLED7_CON();					// initialize debug led
	DEBUGLED7_OFF();
	DEBUGLED8_CON();
	DEBUGLED8_OFF();




	UCSR0B = 0;

	UBRR0L = 3;
	UBRR0H = 0x00;							// Baud Rate 115200

	UCSR0A = 0;
	UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
	UCSR0B = (1<<TXEN0);					// 8 bit char

	DWORD read32;
	WORD read16;
	unsigned char * buffer1;
	buffer1 = malloc(512);




// initialization for VS, SD and FAT
//	OSCCAL = 0x00;						// oscillor calibration, dun know SD's read speed, set to lowest


	_delay_ms(100);

	spi_init();
	PORT_INI();
	if(VS_ini()){
		while(1){
		DEBUGLED2_ON();
		delay500ms();
		DEBUGLED2_OFF();
		delay500ms();
		}
	}

// test play song


	SPCR =  _BV(SPE)|_BV(MSTR);
	SPSR |= _BV(SPI2X);

	DEBUGLED1_ON();
	delay500ms();
	DEBUGLED1_OFF();
	delay500ms();


	SD_Init();
	uint8 SD_try = 0x00;				// since SD is insert by user, we need to check it more patiently
	while ( SD_Reset()){				// SD initialize, if failed, light up debug2 and stop
		SD_try++;
		if ( SD_try > 30 )
		while(1){
			DEBUGLED8_ON();
			delay500ms();
			DEBUGLED8_OFF();
			delay500ms();
		}
	}

	DEBUGLED2_ON();
	delay500ms();
	DEBUGLED2_OFF();
	delay500ms();

	if(FAT_Init()){						// FAT initialization, read the BPB, BS
		while(1){
			DEBUGLED8_ON();
			delay500ms();
			DEBUGLED8_OFF();
			delay500ms();
		}
	}

	DEBUGLED3_ON();
	delay500ms();
	DEBUGLED3_OFF();
	delay500ms();


// play the first song
//		OSCCAL = 0xff;					// now maximize oscillator frequency

	//=====================================================
	//=== this is for debug
	//=====================================================
	DWORD try  = FirstDirSector;
	unsigned char debug1;
	//debug1 = FAT_LoadPartCluster(try,0,buffer1);
	debug1 = FAT_ReadSector(try,buffer1);
	if(debug1==1){
		while(1){
			DEBUGLED2_ON();
			delay500ms();
			DEBUGLED2_OFF();
			delay500ms();
		}
	}else{
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = '1';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'D';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'I';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'R';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ':';
		U_512(buffer1);
	/*	while(1){
			DEBUGLED3_ON();
			delay500ms();
			DEBUGLED3_OFF();
			delay500ms();
		}
	 */
	}


	//=====================================================
	//=== this is for debug
	//=====================================================

		num_songs = 1;
		search(PATH,&MusicInfo,&num_songs,&file_type);  // search songs in root directory

// ============================================================
		//this is for debug only
//================================================================


		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'N';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'A';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'M';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ':';

		unsigned char namecnt;
		unsigned char temp;
		for(namecnt=0;namecnt<8;namecnt++){
			while(!(UCSR0A&(1<<UDRE0)));
			temp=(MusicInfo.deName[namecnt]);
			UDR0 = temp;
		}
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'S';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'I';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = 'S';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ':';

		read32 = MusicInfo.deFileSize;
		U_32(read32);
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';
		while(!(UCSR0A&(1<<UDRE0)));
		UDR0 = ' ';



		read16 = MusicInfo.deStartCluster;
		U_32(read16);

		delay500ms();
		delay500ms();
		delay500ms();
		delay500ms();

// ============================================================
		//this is for debug only
//================================================================



		//=============variable define
			uint16 count;			//data counting
			uint8 i;				//loop variable
			uint16 j;				//loop variable

			uint32 p;									//cluster
			uint32 totalsect;							//total sector of a file
			uint16 leftbytes;							//cotain the left bytes number of a file for the last cluster read
			uint8 *buffer;								//data buffer!!!!!!!!!!!!!!
			uint32 sector;								//record the current sector to judge the end sector

			VS_XCS_H();
			VS_XDCS_L();											// start to write data

			count = 0;

			while(count<2048)					// not for MID format
			{
				if((VS_PIN & _BV(VS_DREQ))!=0){
					for(j=0;j<32;j++){
						VS_WriteDAT(0x00);				//issue 0 seq and wait for DREQ
						count++;
					}
					if(count == 2047)break;
				}
			}

			VS_SoftReset();

			DEBUGLED4_ON();
			delay500ms();
			DEBUGLED4_OFF();
			delay500ms();


			search(PATH,&MusicInfo,&num_songs,&file_type);


			p = MusicInfo.deStartCluster + (((uint32)MusicInfo.deHighClust)<<16);	// it is to find the first cluster of the file

			totalsect = MusicInfo.deFileSize/512;									// song's total sectors
			leftbytes = MusicInfo.deFileSize%512;									// song's last maybe incomplete sector
			i = 0;
			sector = 0;


			//=====================================================
			//=== this is for debug
			//=====================================================
			try  = FirstFATSector;
//			unsigned char debug1;
			debug1 = FAT_ReadSector(try,buffer1);
			if(debug1==1){
				while(1){
					DEBUGLED2_ON();
					delay500ms();
					DEBUGLED2_OFF();
					delay500ms();
				}
			}else{
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = ' ';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = '\\';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = 'F';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = '\\';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = ' ';
				U_512(buffer1);
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = ' ';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = ' ';
				while(!(UCSR0A&(1<<UDRE0)));
				UDR0 = ' ';

			}

/*				while(1){
					DEBUGLED3_ON();
					delay500ms();
					DEBUGLED3_OFF();
					delay500ms();
				}
*/
	        delay500ms();
	        delay500ms();
	        delay500ms();
	        delay500ms();
			//=====================================================
			//=== this is for debug
			//=====================================================

			//free(buffer1);
			unsigned char debug;
			buffer = malloc(512);				// 512 bytes / sector


			while(1){
				for(i=0; i<SectorsPerClust; i++){			// read sectors in a cluster
					debug = FAT_LoadPartCluster(p,i,buffer);	// read one sector to buffer

					//=========================================
					//=======this is for debugg
					//=========================================

					if(debug == 1){
						while(1){
							DEBUGLED7_ON();
							delay500ms();
							DEBUGLED7_OFF();
							delay500ms();
						}
					}else{
/*						while(!(UCSR0A&(1<<UDRE0)));
						UDR0 = ' ';
						while(!(UCSR0A&(1<<UDRE0)));
						UDR0 = ' ';
						while(!(UCSR0A&(1<<UDRE0)));
						UDR0 = 'F';
						while(!(UCSR0A&(1<<UDRE0)));
						UDR0 = 'L';
						while(!(UCSR0A&(1<<UDRE0)));
						UDR0 = ' ';

						U_512(buffer);

						while(1){
							DEBUGLED3_ON();
							delay500ms();
							DEBUGLED3_OFF();
							delay500ms();
						}
*/
					}
/*					delay500ms();
					delay500ms();
					delay500ms();
					delay500ms();
*/
					//=========================================
					//=======this is for debugg
					//=========================================

					count = 0;
				while(count<512){					// try to send one sector every 32 bytes to VS

						if((VS_PIN & _BV(VS_DREQ))!=0)				// wait for DREQ and write 32bytes to VS's buffer
						{
							for(j=0;j<32;j++){
								VS_WriteDAT(buffer[count]); count++;
							}

							if(sector == totalsect && count>=leftbytes)		//file ends here
							{
								i = SectorsPerClust;
								break;					//break from sector, finish this cluster
							}
							if(count == 511){break;}
						}//end if of 32bytes
				}//end of 512 bytes = 1 sector
				sector++;

			}//end of one cluster
			i = 0;

			//=================================
			// this is for debug
			//=================================
/*
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = 'P';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ':';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			read32 = p;
			U_32(read32);
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';

	        delay500ms();
	        delay500ms();
	        delay500ms();
	        delay500ms();

			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = '-';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = '>';
			while(!(UCSR0A&(1<<UDRE0)));

			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
*/
			//=================================
			// this is for debug
			//=================================

			p = FAT_NextCluster(p);	//read next cluster

			//===============================
			//=== this is for debug
			//===============================
/*
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = 'P';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ':';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			read32 = p;
			U_32(read32);
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';
			while(!(UCSR0A&(1<<UDRE0)));
			UDR0 = ' ';

	        delay500ms();
	        delay500ms();
	        delay500ms();
	        delay500ms();
*/

			//===============================
			//=== this is for debug
			//===============================

			if(p == 0x0fffffff || p==0x0ffffff8 ||(FAT32_Enable==0 && p == 0xffff))
			{
				while(1){
					DEBUGLED1_ON();
					delay500ms();
					DEBUGLED1_OFF();
					delay500ms();
				}
			}


		}
		free(buffer);

			while(1){
				DEBUGLED8_ON();
				delay500ms();
				DEBUGLED8_OFF();
				delay500ms();
			}



	//============================
	//====buffer1 for debug======
			free(buffer1);
	//============================
	return 0;


}

